#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define BLOCK_SIZE 1024
#define FREE_BLOCK 0x00000000
#define END_BLOCK 0xFFFFFFFF
#define DIRECTORY 0x01
#define SYSTEM    0x02
#define HIDDEN    0x04
#define READ_ONLY 0x08
#define MODIFIED  0x10
#define HASH_TABLE_SIZE 1000

typedef struct
{
	char file_name[23];
	char attrib;
	unsigned long start_block;
	unsigned long size;
} FILE_DESCRIPTOR;

typedef struct
{
	char file_system_label[20];	
	unsigned long num_blocks;
	unsigned long root_size;
	unsigned long root_offset;
} META_HEADER;

typedef struct node
{
	unsigned long block_num;
	struct node *next;
} NODE;

typedef struct tree_node
{
	FILE_DESCRIPTOR fd;
	struct tree_node *parent;
	struct tree_node *left_sibling;
	struct tree_node *right_sibling;
	struct tree_node *left_child;
} TREE_NODE;

//Manzoor
typedef struct hash_bucket
{
	char file_name[23];
	FILE_DESCRIPTOR fd;
	struct hash_bucket *next;

} HASH_BUCKET;

//Functions to perform all the required operations
int create_vfs(char *vfs_label, unsigned long size);
int mount_vfs(char *vfs_label);
int unmount_vfs(char *vfs_label);

int make_dir(char *parent_path, char *dir_name);
int delete_dir(char *name);
int move_dir(char *source_dir_name, char *dest_dir_name);

int list_dir(char *dir_name, int flag, char *txt_file_path);
int add_file(char *dest_dir_name, char *file_name, char *data);
int list_file(char *file_path,char *txt_file_path);

int update_file(char *file_path, char *data);
int remove_file(char *file_path);
int move_file(char *source_file_path, char *dest_file_path);

int copy_file(char *source_path, char *dest_path);
//Yet to implement
//void exportfile ( char *P1, char *P2 );
//void searchfile ( char *P1, char *P2 );


void mark_free(unsigned long k);
unsigned long write_file(void *buffer, long size);
unsigned long overwrite_file(void *buffer, unsigned long size, FILE_DESCRIPTOR fd);
int read_file(void *buffer, unsigned long size, unsigned long block_no);


//int create(char *dest_dir_name, char *file_name, char *data);

void push(NODE **head, unsigned long data);
unsigned long pop(NODE **head);
unsigned long peek(NODE *head);
void free_free_list();

TREE_NODE *get_tree_node(FILE_DESCRIPTOR fd);
void mark_modified(TREE_NODE *temp);
TREE_NODE *insert_child(TREE_NODE *parent, TREE_NODE *new_tree_node);
void read_dir_tree(TREE_NODE *parent);
void write_dir_tree(TREE_NODE *parent);
TREE_NODE *search_dir_tree(TREE_NODE *parent, char file_name[23]);
TREE_NODE *search_path(TREE_NODE *parent, char *path);
void print_dir_tree(TREE_NODE *parent, int level);
void free_dir_tree(TREE_NODE *parent);
void remove_child(TREE_NODE *parent, char file_name[23]);

extern META_HEADER *HEADER;
extern unsigned long *FAT;
extern TREE_NODE *ROOT;
extern NODE *FREE_LIST;
extern unsigned long FREE_SPACE;
extern FILE *fptr;



